/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id: ext_service.c */
/* 服务管理类 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "main/SAPI.h"
#include "Zend/zend_interfaces.h"
#include "ext/standard/info.h"
#include "ext/standard/php_var.h"
#include "ext/standard/php_string.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/url.h"
#include "ext/pcre/php_pcre.h"
#include "php_ext_framework.h"
#include "ext_service.h"

zend_class_entry *ext_service_ce, *ext_service_filter_impl_ce;

ZEND_BEGIN_ARG_INFO_EX(void_arginfo, 0, 0, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(service_filter_arginfo, 0, 0, 2)
	ZEND_ARG_INFO(0, class_name)
	ZEND_ARG_INFO(0, params)
	ZEND_ARG_INFO(1, result)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(service_after_filter_arginfo, 0, 0, 1)
	ZEND_ARG_INFO(0, after_filter)
	ZEND_ARG_INFO(0, class_name)
	ZEND_ARG_INFO(0, params)
	ZEND_ARG_INFO(0, result)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(service_before_filter_arginfo, 0, 0, 1)
	ZEND_ARG_INFO(0, before_filter)
	ZEND_ARG_INFO(0, class_name)
	ZEND_ARG_INFO(0, params)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(service_create_arginfo, 0, 0, 1)
	ZEND_ARG_INFO(0, class_name)
	ZEND_ARG_INFO(0, params)
ZEND_END_ARG_INFO();

ZEND_METHOD(ext_service, __construct){
	zval *before_func_filter, *after_func_filter;

	MAKE_STD_ZVAL(before_func_filter);
	MAKE_STD_ZVAL(after_func_filter);

	array_init(before_func_filter);
	array_init(after_func_filter);

	zend_update_property(FETCH_THIS, ZEND_STRL("before_func_filter"), before_func_filter TSRMLS_CC);
	zend_update_property(FETCH_THIS, ZEND_STRL("after_func_filter"), before_func_filter TSRMLS_CC);
}

ZEND_METHOD(ext_service, create){
	zval *call_name, *params;
	zval *before_func_filter, *after_func_filter;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z") == FAILURE){
		RETURN_FALSE;
	}

	
}

/**
 * ext_service::before_filter(ext_service_filter $before_filter, 
 *									$class_name=false, 
 *									$params=false)
 */
ZEND_METHOD(ext_service, before_filter){
	zval *callback, *class_name, *params;
	zval *before_func_filter;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z|z") == FAILURE){
		RETURN_FALSE;
	}

	if(Z_TYPE_P(callback) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(callback), ext_service_filter_impl_ce TSRMLS_CC)){
		zend_error(E_ERROR, "callback must implements ext_service_filter");
		RETURN_FALSE;
	}

	before_func_filter = zend_read_property(FETCH_THIS, ZEND_STRL("before_func_filter"), 0 TSRMLS_CC);

	if(Z_TYPE_P(before_func_filter) != IS_ARRAY){
		zend_error(E_ERROR, "before_func_filter must be array");
		RETURN_FALSE;
	}

	add_next_index_zval(before_func_filter, callback);

	RETURN_TRUE;
}

/**
 * ext_service::after_filter(ext_service_filter $after_filter, 
 *									$class_name=false, 
 *									$params=false, 
 *									$result=false)
 */
ZEND_METHOD(ext_service, after_filter){
	zval *callback, *class_name, *params, *result;
	zval *after_func_filter;

	if(Z_TYPE_P(callback) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(callback), ext_service_filter_impl_ce TSRMLS_CC)){
		zend_error(E_ERROR, "callback must implements ext_service_filter");
		RETURN_FALSE;
	}

	after_func_filter = zend_read_property(FETCH_THIS, ZEND_STRL("after_func_filter"), 0 TSRMLS_CC);

	if(Z_TYPE_P(after_func_filter) != IS_ARRAY){
		zend_error(E_ERROR, "before_func_filter must be array");
		RETURN_FALSE;
	}

	add_next_index_zval(after_func_filter, callback);
	RETURN_FALSE;
}

static zend_function_entry ext_service_method[] = {
	ZEND_ME(ext_service, __construct, void_arginfo, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
	ZEND_ME(ext_service, create, service_create_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(ext_service, before_filter, service_before_filter_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(ext_service, after_filter, service_after_filter_arginfo, ZEND_ACC_PUBLIC)
	{NULL, NULL, NULL}
};

static zend_function_entry ext_service_filter_method[] = {
	ZEND_ABSTRACT_ME(ext_service_filter, filter, service_filter_arginfo)
};

/* {{{ PHP_MINIT_FUNCTION
 */
EXT_STARTUP_FUNCTION(service)
{
	zend_class_entry service_ce, service_impl_ce;
	INIT_CLASS_ENTRY(service_ce, "ext_service", ext_service_method);
	INIT_CLASS_ENTRY(service_ce, "ext_service_filter", ext_service_filter_method);

	ext_service_ce = zend_register_internal_class(&service_ce TSRMLS_CC);
	ext_service_filter_impl_ce = zend_register_internal_interface(&service_impl_ce TSRMLS_CC);

	zend_declare_property_null(ext_service_ce, ZEND_STRL("before_func_filter"), ZEND_ACC_PROTECTED TSRMLS_CC);
	zend_declare_property_null(ext_service_ce, ZEND_STRL("after_func_filter"), ZEND_ACC_PROTECTED TSRMLS_CC);
	
	return SUCCESS;
}
/* }}} */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
